%option noyywrap
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int lineNumber = 1;
%}

/* comments */
/* multiple line comments consist either by all chars different from star */
noStar [^*]
/* or there can be a star but NOT followed by a forward slash */
noCommentEnd [*][^/]
comment "/*"({noStar}|{noCommentEnd})*"*/"
commentLine [/][/][^\n]*

/* blocks */
blockStart [{]
blockEnd [}]
/* also paramStart */
listStart [(]
/* also paramEnd */
listEnd [)]
stmtEnd [;]
/* used for switch statement , case 3: --- (bool)? a : b */
selector [:]
listSeparator [,]
questionMark [?]

/* reserved keywords */
IF [iI][fF]
ELSE [eE][lL][sS][eE]
SWITCH [sS][wW][iI][tT][cC][hH]
CASE [cC][aA][sS][eE]
DEFAULT [dD][eE][fF][aA][uU][lL][tT]
DO [dD][oO]
WHILE [wW][hH][iI][lL][eE]
FOR [fF][oO][rR]
CONTINUE [cC][oO][nN][tT][iI][nN][uU][eE]
BREAK [bB][rR][eE][aA][kK]
RETURN [rR][eE][tT][uU][rR][nN]
CONST [cC][oO][nN][sS][tT]
TRUE [tT][rR][uU][eE]
FALSE [fF][aA][lL][sS][eE]

/* types */
CHAR [cC][hH][aA][rR]
INT [iI][nN][tT]
FLOAT [fF][lL][oO][aA][tT]
VOID [vV][oO][iI][dD]
STRING [sS][tT][rR][iI][nN][gG]
BOOL [bB][oO][oO][lL]

/* right values */
plus [+]
minus [-]
digit [0-9]
letter [a-zA-Z]
identifier {letter}({letter}|{digit})*
integer {digit}+
eNotation ([eE]({plus}|{minus})?{digit}+)
floatNumber ({digit}+\.{digit}*)|({digit}*\.{digit}+){eNotation}?
/* string: all except " symbol   [^"]|([\]["])) */
stringValue \"([^"]|([\\]["]))*\"
charValue [']({letter}|{digit})[']

/* conditional/boolean operations */
greater [>]
greaterEqual [>][=]
less [<]
lessEqual [<][=]
equal [=][=]
assignment [=]
NOT [!]
AND [&][&]
OR [|][|]
notEqual [!][=]

/* mathematical operations */
/* addition [+], subtraction [-] not needed since we have already plus and minus */
increment {plus}{plus}
decrement {minus}{minus}
multiplication [*]
division [/]
modulo [%]

%%
[\n] {lineNumber++;}
[ \t\r] {/* ignore white spaces and tabs */}
{commentLine} {/*skip single line comment*/}
{comment} {/*skip multiple line comment*/}

{blockStart} {return blockStart;}
{blockEnd} {return blockEnd;}
{listStart} {return listStart;}
{listEnd} {return listEnd;}
{stmtEnd} {return stmtEnd;}
{selector} {return selector;}
{listSeparator} {return listSeparator;}
{questionMark} {return questionMark;}

{IF} {return IF;}
{ELSE} {return ELSE;}
{SWITCH} {return SWITCH;}
{WHILE} {return WHILE;}
{FOR} {return FOR;}
{CONTINUE} {return CONTINUE;}
{BREAK} {return BREAK;}
{RETURN} {return RETURN;}
{DO} {return DO;}
{CASE} {return CASE;}
{DEFAULT} {return DEFAULT;}
{CONST} {return CONST;}
{TRUE} {return TRUE;}
{FALSE} {return FALSE;}

{CHAR} {return CHAR;}
{INT} {return INT;}
{FLOAT} {return FLOAT;}
{VOID} {return VOID;}
{STRING} {return STRING;}
{BOOL} {return BOOL;}

{identifier} {yylval.lexeme = strdup(yytext); return identifier;}
{integer} {yylval.value = atoi(yytext); return integer;}
{floatNumber} {yylval.value = atof(yytext); return floatNumber;}
{stringValue} {yylval.lexeme = strdup(yytext); return stringValue;}
{charValue} {yylval.lexeme = strdup(yytext); return charValue;}

{greater} {return greater;}
{greaterEqual} {return greaterEqual;}
{less} {return less;}
{lessEqual} {return lessEqual;}
{equal} {return equal;}
{assignment} {return assignment;}
{NOT} {return NOT;}
{AND} {return AND;}
{OR} {return OR;}
{notEqual} {return notEqual;}

{plus} {return plus;}
{increment} {return increment;}
{minus} {return minus;}
{decrement} {return decrement;}
{multiplication} {return multiplication;}
{division} {return division;}
{modulo} {return modulo;}

{commentLine} {/*skip it*/}
{comment} {/*skip it*/}
[^\n] {yyerror("input error - could not interpret input");}
%%


/* not needed if yacc is invoked -> otherwise error: "multiple definition of main"

void yyerror(const char * errorMsg) {
    //use stderr to print on the "error output" stream
    fprintf(stderr, "error at line: %d: %s\n", lineNumber, errorMsg);
    exit(-1);
}

int main(void){
    yylex();
    return 0;
}
*/
